/* 
 * File:   HiddenFiles.cpp
 * Author: Paul Stupka
 * 
 * Created on October 28, 2011, 2:18 AM
 */
#include <cstdlib>
#include <fnmatch.h>
#include "HiddenFiles.h"
#include <cstring>

void HiddenFiles::hide_file(const char* filename) {
    std::string command = "echo ";
    command += filename;
    command += " > /dev/hidefile";
    system(command.c_str());
}

std::set<std::string> HiddenFiles::FindMatches(char* dir, char* pattern, bool recursive)
{
    std::set<std::string> files;
    std::set<std::string>::iterator i;
    if (recursive)
    {
        for (i = hiddenFiles.begin(); i != hiddenFiles.end(); ++i)
        {
            std::string buf;
            if ((*i).find(dir,0)==0)
            {
                buf = (*i).substr((*i).rfind("/")+1);
                if (fnmatch(pattern,buf.c_str(),FNM_NOESCAPE)==0)
                        files.insert(*i);
            }
        }
    }
    else
    {
        for (i = hiddenFiles.begin(); i != hiddenFiles.end(); ++i)
        {
            std::string buf;
            if ((*i).find(dir,0)==0)
            {
                buf = (*i).substr(strlen(dir));
                if (fnmatch(pattern,buf.c_str(),FNM_NOESCAPE)==0)
                        files.insert(*i);
            }
        }
    }
    return files;
}

HiddenFiles::HiddenFiles(std::string configFile, bool firstRun) {
    this->configFile = configFile;
    std::fstream f_in(this->configFile.c_str(), std::ios::in);
    
    if (f_in)
    {
        while (!f_in.eof())
        {
            std::string str;
            f_in>>str;   
            if (str!="")
                hiddenFiles.insert(str);
        }
    }
    f_in.close();
    if (firstRun)
    {
        std::set<std::string>::iterator i;
        for (i = hiddenFiles.begin(); i != hiddenFiles.end(); ++i)
        {       
            struct stat st;
            stat((*i).c_str(), &st);
            if (st.st_gid!=0)
                hide_file((*i).c_str());
        }
    }    
}

HiddenFiles::~HiddenFiles() {
}

void HiddenFiles::Remove(std::set<std::string> files)
{    
    std::set<std::string>::iterator i;
    for (i = files.begin(); i != files.end(); ++i)
    {
        hiddenFiles.erase((*i));
        std::cout<<"File "<<(*i)<<" had been successfully restored!"<<std::endl;
    }
    struct stat st;
    std::fstream f_out(configFile.c_str(), std::ios::out);            
    for (i = hiddenFiles.begin(); i != hiddenFiles.end(); ++i)
    {            
        if (stat((*i).c_str(), &st) == 0)
        {
            f_out<<(*i)<<std::endl;
            hide_file((*i).c_str());        
        }
    }
    f_out.close();
}

void HiddenFiles::Add(std::set<std::string> files)
{
    struct stat st;
    std::fstream f_app(configFile.c_str(), std::ios::out | std::ios::app);
    std::set<std::string>::iterator i;
    for (i = files.begin(); i != files.end(); ++i)
    {
        if (!hiddenFiles.count((*i)))
        {            
            if (stat((*i).c_str(), &st) == 0)
            {                            
                struct stat st;
                stat((*i).c_str(), &st);
                if (st.st_gid!=0)
                {
                    hide_file((*i).c_str());
                    std::cout<<"File "<<(*i)<<" had been successfully hidden!"<<std::endl;
                    f_app<<(*i)<<std::endl;
                }
                else
                {
                    std::cout<<"You are trying to hide system file "<<(*i)<<" Do you want to continue? (y/n) ";
                    char c;
                    do
                    {
                        c = getchar();
                    }while ((c!='y')&&(c!='n'));
                    if (c=='y')
                    {
                        hide_file((*i).c_str());
                        std::cout<<"File "<<(*i)<<" had been successfully hidden!"<<std::endl;
                        f_app<<(*i)<<std::endl;
                    }
                }
            }
            else
                std::cout<<"File "<<(*i)<<" does not exist!"<<std::endl;
        }
        else
        {
            std::cout<<"File "<<(*i)<<" is already hidden!"<<std::endl;
        }    
    }
    f_app.close();
}